home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / prg_casm / recio215.zip / USAGE.TXT < prev   
Text File  |  1996-10-26  |  37KB  |  1,003 lines

  1.     Title: STANDARD USAGE OF C LANGUAGE RECIO LIBRARY
  2. Copyright: (C) 1994-1996, William Pierpoint
  3.   Version: 2.15
  4.      Date: October 26, 1996
  5.  
  6.  
  7.  
  8. 1.0 INTRODUCTION
  9.  
  10. The implementation descibed by this standard usage is a superset of the
  11. recio specification.  Enhancements are noted in the text.
  12.  
  13.  
  14. 1.1 Mnemonics
  15.  
  16. The recio functions have been given a consistent mnemonic naming
  17. convention.  All recio functions are in lower case and start with
  18. the letter r.  Function names are analogous to <stdio.h> functions.
  19. Mnemonics are as follows:
  20.  
  21. Single letter (field functions)               Multi-letter
  22. ----------------------------------------      -----------------
  23. b - base (prefix)                             beg - beginning
  24. c - column (prefix), character (suffix)       ch  - character
  25. d - double (suffix)                           col - column
  26. f - float (suffix)                            cxt - context
  27. i - integer (suffix)                          eof - end of file
  28. l - long (suffix)                             err - error
  29. n - number                                    fld - field buffer
  30. r - record pointer (first letter)             fmt - format  
  31. s - string pointer (suffix)                   fn  - function
  32. t - time_t time (suffix)                      no  - number         
  33. u - unsigned (suffix)                         num - number
  34.                                                 rec - record buffer  
  35.                           siz - size of buffer
  36.                           str - string
  37.                           tm  - struct tm time
  38.                           txt - text           
  39.  
  40. 1.2 Order
  41.  
  42. The order in which the prefix mnemonics appear indicates the order in which
  43. the arguments appear in the function.  The suffix mnemonics of the input
  44. functions tell you what the function returns.  The suffix mnemonics of the
  45. output functions indicate the last argument and tell you what the function
  46. outputs.  All output functions return an integer with a zero value if the
  47. function executed successfully.
  48.  
  49. For example, the input function rbgetui():
  50.  
  51.     arguments:  r - record pointer
  52.                 b - base (radix)
  53.       returns: ui - unsigned integer
  54.  
  55. The output function rbputui():
  56.  
  57.     arguments:  r - record pointer
  58.                 b - base (radix)
  59.                ui - unsigned integer is output
  60.  
  61. Note: c is used in the prefix of a function's name only once even if there are
  62.       two column arguments.  If the function inputs or outputs a character,
  63.       there is only one column argument; otherwise there are two.
  64.  
  65.  
  66.  
  67. 2.0 ERRORS AND WARNINGS
  68.  
  69. The functions declared in the header <recio.h> make use of the errno macro
  70. defined in section 4.1.3 of ANSI X3.159-1989.  This mechanism was chosen
  71. because (1) the <stdlib.h> conversion functions (strtod(), strtol(), etc.)
  72. make use of this error reporting mechanism and (2) the <recio.h> functions
  73. make use of the <stdlib.h> conversion functions.
  74.  
  75. In this implementation, errno can return the following macro constants:
  76.  
  77.          0 - No error.
  78.     EACCES - permission denied.
  79.       EDOM - argument out of domain.
  80.     EINVAL - invalid argument.
  81.     EMFILE - too many open files.
  82.     ENOENT - no such file or directory.
  83.     ENOMEM - out of memory.
  84.     ERANGE - out of range.
  85.  
  86. where
  87.  
  88. * EACCESS means that you don't have permission to access this file.  All
  89.   MSDOS files have read permission.
  90.  
  91. * EDOM says that the argument is ouside of the defined domain.  For 
  92.   example, if the days of the month are defined as 1 to 31 and you 
  93.   convert a string "1/32/1995" using sftotm(), an EDOM error will occur.
  94.  
  95. * EINVAL indicates an invalid argument to a function, usually a NULL record
  96.   pointer.  This is most often caused by a programming error.
  97.  
  98. * EMFILE means the program tried to open more files than the maximum allotted
  99.   by ROPEN_MAX or FOPEN_MAX.  If your program is interactive, the user can
  100.   close one or more open record streams.  Or you might decide that ROPEN_MAX
  101.   or FOPEN_MAX needs to be a larger value.
  102.  
  103. * ENOENT says that ropen() could not find the requested file to open.
  104.   Perhaps the name of the file was misspelled, or your program looked in
  105.   wrong directory.  If your program was trying to read a configuration file,
  106.   it could use internal default values when the configuration file does
  107.   not exist.
  108.  
  109. * ENOMEM indicates that the program ran out of heap space.  You may be able
  110.   to correct this if you are able to deallocate memory you no longer need.
  111.   For example, you could reduce the size of buffers when the size only
  112.   affects speed.  Such buffers need to be flushed first.  Buffers used by
  113.   the recio library do not fit this criteria.
  114.  
  115. * ERANGE tells you that the data is outside the capabilities of the data 
  116.   type to represent it.  The data value is either too large or too small.  
  117.   Either the data is incorrect or you need a more robust data type to hold 
  118.   the data.
  119.  
  120. Beginning with version 1.1, recio functions set errno when the record
  121. pointer is invalid and set an internal error number when the record pointer
  122. is valid.  The recio error number is accessed through the rerror function.
  123.  
  124. The rerror function can return the following macro constants:
  125.  
  126.          0 - No error.
  127.     R_EDOM - out of domain.
  128.   R_EINVAL - invalid argument (not the record pointer).
  129.  R_EINVDAT - invalid data.
  130.  R_EINVMOD - invalid mode.
  131.  R_EMISDAT - missing data.
  132.   R_ENOMEM - out of memory.
  133.   R_ENOGET - input record too long.
  134.   R_ENOPUT - unable to write data to output.
  135.   R_ERANGE - out of range.
  136.   R_EFAULT - application defined error.
  137.  
  138. where
  139.  
  140. * R_EDOM indicates an argument to a function is outside the defined 
  141.   domain.  For example, if base is defined to have a valid range of 
  142.   2 - 32 and you pass a 1, an R_EDOM error occurs.
  143.   
  144.   If the following conditions are not met, an R_EDOM error will result:
  145.   
  146.   Input of integral numbers:  2 <= base <= 32 or base==0
  147.   Output of integral numbers: 2 <= base <= 32
  148.   Input of time:              1 <= month <= 12
  149.                               1 <= day <= 31
  150.                               0 <= hour <= 23
  151.                               0 <= minute <= 59
  152.                               0 <= second <= 61 (includes 2 leap seconds)
  153.  
  154. * R_EINVDAT says the data is invalid.  Invalid data is caused by an
  155.   unrecognized character in the field.  For example, if you read an 
  156.   integral number that contained a letter, a R_EINVDAT error would 
  157.   occur.
  158.  
  159. * R_EINVMOD indicates that you opened a file in read mode, then used an 
  160.   output function or opened a file in write or append mode, then used an 
  161.   input function.
  162.  
  163. * R_EMISDAT says the data is missing.  Missing data means the field is empty.
  164.   If you expect a number, you could substitute either zero or some unique
  165.   number to indicate an empty field.
  166.  
  167. * R_ENOMEM indicates that the program ran out of heap space.  You may be able
  168.   to correct this if you are able to deallocate memory you no longer need.
  169.   For example, you could reduce the size of buffers when the size only
  170.   affects speed.  Such buffers need to be flushed first.  Buffers used by
  171.   the recio library do not fit this criteria.
  172.  
  173. * R_ENOGET is caused by a record being longer than size_t.  Most probable 
  174.   cause is from trying to read a binary file.
  175.  
  176. * R_ENOPUT says the program was unable to write the data to the output.  
  177.   One possible cause is that the disk is full.
  178.  
  179. * R_ERANGE tells you that the data is outside the capabilities of the
  180.   data type to represent it.  For instance, suppose you used rgeti() 
  181.   to get an integer and the data value is 32768.  If a 16-bit integer 
  182.   has an upper limit of 32767, the value is too large.  If the data is 
  183.   wrong, you can have the error function correct it.  If the data is 
  184.   right, you need to correct the data type within the program.
  185.  
  186.   If the following types of data are not within the following ranges,
  187.   a R_ERANGE error will occur:
  188.   
  189.   integer: INT_MIN <= x <= INT_MAX
  190.   long: LONG_MIN <= x <= LONG_MAX
  191.   unsigned integer: 0 <= x <= UINT_MAX
  192.   unsigned long: 0 <= x <= ULONG_MAX
  193.   float: -FLT_MAX <= x <= -FLT_MIN or FLT_MIN <= x <= FLT_MAX or x==0.0
  194.   double: -DBL_MAX <= x <= -DBL_MIN or DBL_MIN <= x <= DBL_MAX or x==0.0
  195.   time_t: TIME_T_MIN <= x <= TIME_T_MAX
  196.  
  197. * R_EFAULT can be used with rseterr() in your own application.
  198.  
  199. The recio library also has warning numbers.  There is not a global warning 
  200. number equivalent to errno.  The warning indicator is associated with a 
  201. record stream.  Thus warnings can only be set for valid record streams.  
  202. The warning number for a record stream is accessed through the rwarning 
  203. function.
  204.  
  205. The rwarning function can return the following macro constants:
  206.  
  207.          0 - No warning.
  208.  R_WEMPSTR - empty data string.
  209.   R_WNOREG - unable to register exit function with atexit().
  210.   R_WWIDTH - data too wide for columnar output.
  211.   R_WTMFMT - incomplete data in a time field.
  212.   R_WFAULT - application defined warning.
  213.  
  214. where
  215.  
  216. * R_WEMPSTR says that an empty data string was input.  If you want to
  217.   substitute another string from within your program, use the rsetfldstr 
  218.   function in your callback warning function to place the new string 
  219.   into the field buffer.
  220.  
  221. * R_WWIDTH indicates that on output, the data will not fit between the
  222.   columns specified.  If the data is numeric, the recio output functions
  223.   write asterisks to the output; if the data is a string, a truncated string
  224.   is written.
  225.  
  226. * R_WNOREG means the program was unable to register the internal recio exit
  227.   function with the ANSI atexit() function.  The internal recio exit
  228.   function ensures that all open record streams are closed and all dynamic
  229.   memory allocated by the recio library is deallocated.
  230.  
  231. * R_WTMFMT means the data in a time field was incomplete.  For example, 
  232.   the time format may have been looking for a date and a time of day but 
  233.   the time field only contained a date.  Data is only compared left to 
  234.   right.  Any mismatch in the delimiters that separate the time elements 
  235.   (month, hour, etc) generates an R_EINVDAT error.
  236.  
  237. * R_WFAULT can be used with rsetwarn() in your own applications.
  238.  
  239.  
  240. 2.1 Define Callback Error Function
  241.  
  242. First define a callback error function to be used by the recio functions.
  243. You may give the function any name you wish.  In the sample function below,
  244. the name rerrfn is used.  The function takes one argument, a record pointer
  245. (REC *).  It returns nothing (void).  The function must first check for a
  246. valid record pointer using the risvalid function.  Other than that, you can
  247. customize it to do whatever you want.
  248.  
  249. A simple callback error function rerrmsg is included in the RECIO library.  
  250. In the initial prototyping stages of development, you may wish to use this 
  251. function rather than taking the time to develop your own function.  Later 
  252. you can substitute a more robust callback error function.
  253.  
  254. The recio functions use a callback error function in order to give the most 
  255. flexibility in handling errors.  The rerrfn function shown below just sends
  256. information to stderr.  You may wish to send information to a printer, a 
  257. file, a window, or a dialog box.  You might even want to give users the 
  258. ability to examine errors and enter corrections.  If the error is corrected, 
  259. you will want to call the rclearerr function before your callback error 
  260. function returns.
  261.  
  262. When your callback error function is invoked, check rerror() or errno
  263. to determine the cause of the error.
  264.  
  265. The main purpose of this sample callback error function is to show some of
  266. kinds of things you can do in a callback error function.  Note that when an
  267. error occurs, the column number indicator rcolno() has moved just beyond
  268. the error.  To make it clearer to the user where the error occurred, rerrfn()
  269. displays rcolno()-1, but not less than rbegcolno(), the column number for the
  270. first column.
  271.  
  272. A more detailed callback error function is given in the source code for the
  273. test program TESTCHG.C.  The test program callback error function makes use
  274. of the rfix functions to fix up bad data (primarily overflows and underflows)
  275. and continue processing.  If appropriate for your application, you can use
  276. these functions as well.  They have been compiled into the recio libraries
  277. for your potential use.
  278.  
  279. /* define callback error function */
  280. void rerrfn(REC *rp)
  281. {
  282.     /* if rp is a valid record pointer */
  283.     if (risvalid(rp)) {
  284.  
  285.       /* if reof indicator set */
  286.       if (reof(rp)) {
  287.           fprintf(stderr, "ERROR reading %s -- "
  288.            "tried to read past end of file\n\n", rnames(rp));
  289.  
  290.       /* else rerror indicator set */
  291.       } else {
  292.  
  293.           /* determine cause of error */
  294.           switch (rerror(rp)) {
  295.  
  296.           /* input data errors */
  297.           case R_ERANGE:
  298.           case R_EINVDAT:
  299.           case R_EMISDAT:
  300.           /* output data errors */
  301.           case R_ENOPUT:
  302.  
  303.               /* print location of error */
  304.               fprintf(stderr, "DATA ERROR in FILE %s at LINE %ld,"
  305.                " FIELD %u, COLUMN %u -- %s\n", rnames(rp), rrecno(rp),
  306.                rfldno(rp), max(rcolno(rp)-1, rbegcolno(rp)), rerrstr(rp));
  307.               break;
  308.  
  309.           /* fatal errors (R_EINVMOD, R_EINVAL, R_ENOMEM) */
  310.           default:
  311.             fprintf(errout, "FATAL ERROR reading FILE %s -- %s\n",
  312.              rnames(rp), rerrstr(rp));
  313.             abort();
  314.             break;
  315.           }
  316.       }
  317.  
  318.     /* else invalid record pointer */
  319.     } else {
  320.         switch (errno) {
  321.  
  322.         /* non-fatal errors */
  323.         case EACCES:
  324.         case EMFILE:
  325.           fprintf(errout, "WARNING: %s\n", strerror(errno));
  326.           break;
  327.  
  328.         /* fatal errors (EINVAL, ENOMEM) */
  329.         default:
  330.           fprintf(errout, "FATAL ERROR: %s\n", strerror(errno));
  331.           abort();
  332.           break;
  333.         }
  334.     }
  335. }
  336.  
  337.  
  338. 2.2 Define Callback Warning Function
  339.  
  340. Next define a callback warning function.  You may give the function any name
  341. you want.  In the sample function below, the name rwarnfn is used.  The
  342. function takes one argument, a record pointer (REC *).  It returns nothing
  343. (void).
  344.  
  345. A simple callback warning function rwarnmsg is included in the recio library.  
  346. In the initial prototyping stages of development, you may wish to use this 
  347. function rather than taking the time to develop your own function.  Later 
  348. you can substitute a more robust callback warning function.
  349.  
  350. The recio functions use a callback warning function in order to give the
  351. most flexibility in handling unusual conditions.  For example, the recio
  352. library considers empty data strings to be legal but your application may
  353. want to flag an empty data string as a data error.  You can do that by
  354. checking for R_WEMPSTR warnings in your callback warning function.
  355.  
  356. When your callback warning function is invoked, check rwarning() to
  357. determine the cause of the warning.
  358.  
  359. You can also use your callback warning function to keep track of the number
  360. of warnings, then print a summary of any warnings just before you close a
  361. record stream.  You will find an example in the test program TESTCHP.C.
  362.  
  363. void rwarnfn(REC *rp)
  364. {
  365.   if (risvalid(rp)) {
  366.     switch (rwarning(rp)) {
  367.     case R_WNOREG:   /* atexit() full */
  368.       fprintf (errout, "WARNING %s\n", rwarnstr(rp));
  369.       break;
  370.     case R_WEMPSTR:  /* empty data string */
  371.     case R_WWIDTH:   /* data too wide for columns */
  372.     case R_WTMFMT:   /* time data incomplete */
  373.       fprintf(errout, "WARNING reading %s at record %lu and field %u -- %s\n",
  374.        rnames(rp), rrecno(rp), rfldno(rp), rwarnstr(rp));
  375.       break;
  376.     }
  377.   }
  378. }
  379.  
  380. 2.3 Register Callback Error and Warning Functions
  381.  
  382. Once you have written your callback error and warning functions, you must let
  383. the other recio functions know that they exist.  You use the rseterrfn and
  384. rsetwarnfn functions to individually register your callback functions or 
  385. the rinit to register both functions at once.  You may find use of rinit 
  386. easier to remember.
  387.  
  388.     /* register callback error and warning functions */
  389.     rseterrfn(rerrfn);
  390.     rsetwarnfn(rwarnfn);
  391.  
  392. OR
  393.  
  394.     /* register callback error and warning functions */
  395.     rinit(rerrfn, rwarnfn);
  396.  
  397. OR to use the simple built-in callback error/warning functions
  398.  
  399.     /* register built-in callback error and warning functions */
  400.     rinit(rerrmsg, rwarnmsg);
  401.  
  402.  
  403. OR to use the simple built-in error function without a warning function
  404.  
  405.     /* register callback error function */
  406.     rinit(rerrmsg, NULL);
  407.  
  408.  
  409.  
  410. 3.0 OPEN FILE
  411.  
  412.  
  413. 3.1 Open File and Get Record Pointer
  414.  
  415. Use the ropen function to open the file you want to read, write, or append.
  416. Store the record pointer returned by the ropen function.  Do not open recin,
  417. recout, recerr, or recprn (MSDOS printer).  They are always open, so they do
  418. not need to be opened or closed.
  419.  
  420.     REC *rp = ropen("FILENAME.DAT", "r");
  421.  
  422.  
  423. 3.2 Check Record Pointer
  424.  
  425. Following the ropen function, you need to check to see if the file was
  426. opened correctly.  If ropen returned a NULL pointer, then the file was not
  427. opened.
  428.  
  429. Errors other than ENOENT are reported to your callback error function.
  430. ENOENT is not reported since you may want to use default values if the
  431. data file is not available.
  432.  
  433.     /* if ropen() failed */
  434.     if (!rp) {
  435.         /* if it failed because file does not exist */
  436.         if (errno==ENOENT) {
  437.             /* action to take when file does not exist */
  438.             ...
  439.         }
  440.     /* else ropen() succeeded */
  441.     } else {
  442.         /* set up stream (see sections 3.3 - 3.6) */
  443.         ...
  444.         /* read or write file (see sections 4 and 5) */
  445.         ...
  446.         /* close file (see section 6) */
  447.         rclose(rp);
  448.     }
  449.  
  450.  
  451. 3.3 Set Field and Text Delimiters and Time Format
  452.  
  453. The space character is the default value for both the field and text
  454. delimiters.  The space character matches any white space.  The default 
  455. time format string is "%m/%d/%y".  If you need to something else, use 
  456. the rsetfldch, rsettxtch, and rsettmfmt functions to explicitly set the 
  457. values.  Application maintenance will be easier if you get in the habit 
  458. of setting these values for each record stream.
  459.  
  460.     rsetfldch(rp, ',');         /* set field delimiter character */
  461.     rsettxtch(rp, '"');         /* set text delimiter character */
  462.     rsettmfmt(rp, "%m/%d/%Y");  /* set time format */
  463.  
  464.  
  465. 3.4 Set Field and Record Buffer Sizes
  466.  
  467. Setting the field and record buffer sizes is optional.  Buffers will be
  468. automatically reallocated as necessary.  However if you set the field and
  469. record sizes in advance to the maximum value needed, you can reduce memory
  470. fragmentation.  The field and record buffers are not used for output streams.
  471.  
  472.     rsetfldsiz(rp, 41);  /* set size of field buffer */
  473.     rsetrecsiz(rp, 133); /* set size of record buffer */
  474.  
  475.  
  476. 3.5 Set Context Number
  477.  
  478. If your application opens record streams with more than one data format, you
  479. will want to set a context number.  You use the context number so that your
  480. callback error function can determine (using the rcxtno function) which data
  481. format it is dealing with.  Each context number must be a positive integer;
  482. zero and negative numbers are reserved.  Predefined context symbolic
  483. constants are RECIN, RECOUT, RECERR, and (for MSDOS) RECPRN.
  484.  
  485. #define SOILS_DB      1
  486. #define BUILDINGS_DB  2
  487.  
  488.     rsetcxtno(rp, SOILS_DB); /* set context number */
  489.  
  490.  
  491. 3.6 Set Beginning Column Number
  492.  
  493. The first column number in the record buffer defaults to zero.  If you prefer
  494. column numbering to start at one, use the rsetbegcolno function.  It is mainly
  495. useful if using column delimited data.  If a number takes up the first ten
  496. columns of the record, the column numbering will be 0 to 9 if rsetbegcolno()
  497. is set to 0, or 1 to 10 is rsetbegcolno() is set to 1.
  498.  
  499.     rsetbegcolno(rp, 1); /* first column is column 1 */
  500.  
  501.  
  502. 3.7 Set Beginning Year
  503.  
  504. If you are going to read time data (time_t or struct tm) using the %y 
  505. time format, you may need to set the beginning year.  The %y format 
  506. represents the year as a two digit number.  Thus the year 76 may represent 
  507. 1776 if your application deals with the signing of the U.S. Declaration 
  508. of Independence, or 1976 if your application deals with the 20th Century.  
  509. The default beginning year is controlled by RECBEGYR and is set in recio.h 
  510. to 1951.  Thus the default range for the %y format corresponds to the years 
  511. 1951 to 2050.
  512.  
  513.     rsetbegyr(1980);  /* %y range 1980 to 2079 */
  514.  
  515. Note that the rsetbegyr function applies globally to the application;
  516. it does not contain a record stream argument.
  517.  
  518. You could also have an application that sets the beginning year dynamically.
  519. The implementation below is restricted by the range of time_t.
  520.  
  521.     time_t curtime;      /* current time */
  522.     struct tm *curtmp;   /* pointer to current tm */
  523.     
  524.     if (time(&curtime) != (time_t) -1) {
  525.         curtmp = localtime(&curtime);
  526.         rsetbegyr(curtmp->tm_year + 1900 - 50); /* current year - 50 years */
  527.     } else {
  528.         rseterr(NULL, EDOM);
  529.     }
  530.  
  531.  
  532.     
  533. 4.0 RECORD FUNCTIONS
  534.  
  535. 4.1 The rgetrec Function
  536.  
  537. If all the records in a data file have the same format, you will want to
  538. loop through all the records until the end of file is reached.  If each
  539. record has a different format, you must call the rgetrec function each
  540. time you want to get the next record.  Calling rgetrec() is optional for
  541. the first record.
  542.  
  543.     /* read all records in file */
  544.     while (rgetrec(rp)) {
  545.         /* Section 5 field functions go here ... */
  546.     }
  547.  
  548.  
  549. 4.2 The rputrec Function
  550.  
  551. After you write all the fields in one record, use the rputrec function
  552. to put the end-of-record newline character to the output and to reset the
  553. internal recio library variables for the next record.
  554.  
  555.     /* write end-of-record */
  556.     rputrec(rp);
  557.  
  558.  
  559. 4.3 The rrecs Macro
  560.  
  561. To get a pointer to the start of the record buffer, use the rrecs macro.
  562.  
  563.     /* echo record contents to stdout */
  564.     printf("%s\n", rrecs(rp));
  565.  
  566.  
  567. 4.4 The rrecno Macro
  568.  
  569. To get the record number, use the rrecno macro.
  570.  
  571.     /* echo record number and record contents to stdout */
  572.     printf("%ld: %s\n", rrecno(rp), rrecs(rp));
  573.  
  574.  
  575. 4.5 The rsetrecstr Function
  576.  
  577. There may be times when you will find it useful to stuff the record buffer
  578. with your own string, then use the field input functions to scan the fields.
  579. Use the rsetrecstr function for this.
  580.  
  581. 4.6 The rresetrec Macro
  582.  
  583. The rresetrec macro resets internals so that you can start reading fields
  584. from the beginning of the record buffer.  This allows you to scan through
  585. the fields in the record buffer multiple times.
  586.  
  587.  
  588. 5.0 GET AND PUT FIELD DATA
  589.  
  590. 5.1 Field functions
  591.  
  592. There are 70 functions that can be used to read or write data.  A mnemonic
  593. system makes it easy to construct the name of any function you need.  Here
  594. are the rules: 
  595.  
  596.  1. There are six prefixes, two bodies, and up to ten suffixes. 
  597.     
  598.     Prefix   Body   Suffix      Prefix   Body   Suffix
  599.     ------   ----   ------      ------   ----   ------
  600.       r       get      c          rb      get      i
  601.       rc      put      d          rcb     put      l
  602.       rn               f          rnb             ui
  603.                        i                          ul
  604.                        l
  605.                        s
  606.                        t
  607.                       tm
  608.                       ui
  609.                       ul
  610.  
  611.   
  612.  2. The rn and rnb prefixes are only used with the get functions.
  613.  
  614.  3. If the prefix contains the letter 'c', it is a column delimited field 
  615.     function.
  616.  
  617.  4. If the prefix contains the letter 'n', it is a character delimited 
  618.     field function that lets you jump directly to the field number before 
  619.     reading the data.  
  620.     
  621.  5. If the prefix contains the letter 'b', it is a field function that 
  622.     reads or writes an integral number in a specified base (radix).  
  623.  
  624.  6. The get body is used to read data, the put body is used to write data.
  625.  
  626.  7. The ten suffixes indicate the ten data types: character, double, float, 
  627.     integer, long, string, time_t, struct tm, unsigned integer, and unsigned 
  628.     long.
  629.  
  630.  
  631. 5.2 The rskipfld Macro and rskipnfld Function
  632.  
  633. If your application does not need to read the data in a field, you can skip
  634. over the field by using the rskipfld macro.
  635.  
  636.     rskipfld(rp);
  637.  
  638. If your application does not need to read the data in several adjacent
  639. fields, you can skip over the fields by using the rskipnfld function.
  640.  
  641.     /* skip over three fields */
  642.     rskipnfld(rp, 3);
  643.  
  644.  
  645. 5.3 The rgotofld Function
  646.  
  647. If your application needs to jump around to different fields in a 
  648. character delimited record, use the rgotofld function.  You can jump 
  649. to fields in any order.  
  650.  
  651. The first field in a data record is field number 1.  However don't 
  652. confuse the field number here with rfldno.  They are not always the same.  
  653. You can understand this better by referring to the diagram below for a 
  654. comma delimited record with three fields.
  655.  
  656.          data:         1  ,    2  ,    3    
  657.      rgotofld:     1       2       3       4
  658.        rfldno:     0 1 1 1 1 2 2 2 2 3 3 3 3
  659.    processing:       rgeti   rgeti   rgeti
  660.  
  661. The multiple values for rfldno in the diagram represent how rfldno 
  662. changes in value as the fields in the record are read sequentially 
  663. using three rgeti calls.
  664.  
  665. If you use rgotofld to go to field 1, you go to rfldno 0.  As the data
  666. in field 1 is processed using an rget function, rfldno quickly changes 
  667. to 1. If an error occurs while processing the first field, rfldno will be 
  668. 1 and can be used within the error or warning callback function to 
  669. indicate which field had an error.  Thus in the context of an error or 
  670. warning callback function, the field number and rfldno are the same, 
  671. but in the context of the rgotofld function, the field number is greater 
  672. than rfldno by 1.
  673.  
  674. Note that although this record has 3 fields, you can go to field 4.  If 
  675. you attempt to go to any field beyond the last field in the record, you 
  676. will be at the end of the record.  No error occurs until you attempt 
  677. to get the data from the field using an rget function.
  678.  
  679.     /* go to field number 3 */
  680.     rgotofld(rp, 3);
  681.  
  682. Since you probably are going to read the field after moving to it, you 
  683. can use the rnget and rnbget series of functions to move to a field 
  684. and read from it in one step.
  685.  
  686.  
  687. 5.4 The ristxtfld Macro
  688.  
  689. You can use the ristxtfld macro to determine if the current field (the field
  690. most recently input or output) was quoted with the text delimiter character
  691. (provided the text delimiter character is not the space character).  For
  692. example, if you need to write out a string field in the same format in
  693. which was read, you can use this macro to determine if the original field
  694. was quoted.
  695.  
  696.     /* write field in same format as read */
  697.     rgets(recin);
  698.     if (ristxtfld(recin)) rsettxtch(recout, '"');
  699.     else rsettxtch(recout, ' ');
  700.     rputs(recout, rflds(recin));
  701.  
  702.  
  703. 5.5 The reof Macro
  704.  
  705. Use the reof macro to determine when the record stream has reached the
  706. end of file.
  707.  
  708.     /* if error or end of file reached */
  709.     while (rgetrec(rp)) {
  710.     ...
  711.     }
  712.     /* if end of file */
  713.     if (reof(rp)) {
  714.        ...
  715.     /* else error */
  716.     } else {
  717.        ...
  718.     }
  719.  
  720.  
  721. 5.6 The rerror Function
  722.  
  723. Use the rerror function to determine if an error has occurred on a record
  724. stream.  You can access a text string for the error using the rerrstr
  725. function.
  726.  
  727.     if (rerror(rp))
  728.         printf("ERROR reading %s - %s\n",
  729.          rnames(rp), rerrstr(rp));
  730.     rclose(rp);
  731.  
  732. It is a good practice to check for any errors just before closing
  733. a record stream.  If the error indicator is clear, you have additional
  734. confidence that the stream was processed correctly.
  735.  
  736.  
  737. 5.7 The rseterr Function
  738.  
  739. If you write wrapper functions or other functions that interact with
  740. recio functions, your code will need to handle errors.  If can use
  741. the rseterr function to set the error number and to call the record
  742. stream callback error function.
  743.  
  744. /* get integer and validate range */
  745. int rrgeti(REC *rp, int min, int max) {
  746.     int result;
  747.  
  748.     result = rgeti(rp);
  749.     if (result < min || result > max) {
  750.         rseterr(rp, R_ERANGE);
  751.     }
  752.     return result;
  753. }
  754.  
  755.  
  756. 5.8 The rwarning Function
  757.  
  758. Use the rwarning macro to determine if a warning has occurred on a record
  759. stream.
  760.  
  761.     if (rwarning(rp)) {
  762.         printf("ERROR %s - %s\n", rnames(rp), rwarnstr(rp));
  763.     }
  764.  
  765. It is good practice to check for any warnings just before closing an output
  766. record stream.
  767.  
  768.  
  769. 5.9 The rsetwarn Function
  770.  
  771. If you write wrapper functions or other functions that interact with recio
  772. functions, you may need to provide warnings.  The rsetwarn function sets the
  773. warning number and calls the record stream callback warning function.
  774.  
  775.     rsetwarn(rp, R_WWIDTH);
  776.  
  777.  
  778. 5.10 The rnumfld Function
  779.  
  780. You can determine the number of character delimited fields in the current
  781. record of an input record stream with the rnumfld function.
  782.  
  783.     unsigned numfld;
  784.     
  785.     numfld = rnumfld(recin);
  786.     
  787.  
  788. 5.11 The rgetfldpos and rsetfldpos Functions
  789.  
  790. If you want to mark a specific position within the current record and later 
  791. return to the same position, use the rgetfldpos and rsetfldpos functions. 
  792. If the record number has changed between calls, a R_EINVAL error is generated 
  793. and passed to the callback error function.  The pos argument is passed by 
  794. reference, but a macro takes care of placing the & for you.
  795.  
  796.  
  797.      rpos_t pos;
  798.      
  799.      rgetrec(recin);
  800.      rgetfldpos(recin, pos);   /* get bookmark at start of record */
  801.      rskipnfld(recin, 3);      /* skip three fields */
  802.      rsetfldpos(recin, pos);   /* reset to bookmark position */
  803.  
  804.  
  805.  
  806. 6.0 CLOSE FILE
  807.  
  808. 6.1 Close File
  809.  
  810. When finished reading or writing a data file, close it.  Do not close recin,
  811. recout, recerr, or recprn as they are always open.
  812.  
  813.     /* close record file */
  814.     rclose(rp);
  815.  
  816.  
  817. 6.2 Close All Files
  818.  
  819. Rather than closing record files one at a time, one can close all open
  820. record files at once using the rcloseall function.
  821.  
  822.     /* all done */
  823.     rcloseall();
  824.  
  825.  
  826.  
  827. 7.0 STRING FUNCTIONS
  828.  
  829. The recio library contains a small set of string functions.  Ideally these 
  830. would be part of a larger separate string library, but are included here 
  831. because the recio functions need them.  You may also find them useful for 
  832. your application.
  833.  
  834.  
  835. 7.1 Trim a string
  836.  
  837. The scntrimbegs, scntrimends, and scntrims functions allow you to trim the 
  838. same character from the beginning, end, and both ends of string up to the 
  839. maximum number specified by the last argument.  The sctrimbegs, sctrimends, 
  840. and sctrims functions let you to trim all multiple occurances of the same 
  841. character from the beginning, end, and both ends of a string.  If you 
  842. specify the space character, all whitespace is trimmed.  You can use the 
  843. strimbegs, strimends, and strims macros to trim whitespace from the ends.
  844.  
  845.     char str[]="\t  Hello, World?!!!\n";
  846.     
  847.     strims(str);              /* trim whitespace from both ends of string */
  848.     sctrimends(str, '!');     /* then trim all ! chars from end of string */
  849.     scntrimends(str, '?', 1); /* finally trim one ? char from end of string */
  850.  
  851.  
  852. 7.2 Dynamically copy and concatenate a string
  853.  
  854. The scpys and scats macros are used to dynamically copy and concatenate a 
  855. string.  To use these macros you must adhere to these points:
  856.  
  857.      1. Initialize pointers of destination strings to NULL.
  858.      2. These macros pass the destination string by reference (and place
  859.         the & for you).
  860.      3. A pointer to the destination string is returned.
  861.      4. Free any dynamically allocated strings when finished with them.
  862.      
  863.      char *dst=NULL;
  864.      char src1[]="Hello ";
  865.      char src2[]="world";
  866.      
  867.      scpys(dst, src1);
  868.      puts(scats(dst, src2));  /* "Hello world" */
  869.  
  870.      /* however the following will not work here as in C++ where you can 
  871.       * declare a function to pass an argument by reference, i.e. 
  872.       * char *scats(char *&dst, const char *src)
  873.       *
  874.       * puts(scats(scpys(dst, src1), src2));  /* C++ */
  875.       */
  876.      
  877.      free(dst);
  878.  
  879.  
  880.  
  881. 8.0 TIME CONVERSION FUNCTIONS
  882.  
  883. The recio library contains a few time conversion functions.
  884.  
  885.  
  886. 8.1 Convert from string to time_t or struct tm types.
  887.  
  888. You can convert a string to either the time_t or struct tm time types using 
  889. the sftotime or sftotm functions.  These functions complement the ANSI 
  890. X3.159-1989 strftime function.  However sftotime and sftotm use a subset 
  891. of the specifiers found with strftime.  The recio library uses the sftotime 
  892. and sftotm functions to get time from the input stream, but uses the strftime 
  893. function to put time to the output stream.  As a consequence, you can use the 
  894. complete set of strftime specifiers for any output you do not later have to 
  895. read back into a program.  If there is an error, the struct tm type will 
  896. contain the time "01/01/70 00:00:00" and the time_t type will contain the 
  897. value (time_t)-1, i.e. cast -1 to a time_t type.
  898.  
  899.  
  900.      time_t time;
  901.      struct tm t;
  902.      
  903.      time = sftotime("11/24/94", "%m/%d/%y");
  904.      t = sftotm("11/24/94", "%m/%d/%y");
  905.  
  906.  
  907. 8.2 Convert between time_t and struct tm types.
  908.  
  909. You can convert between the time_t and struct tm types using the tmtotime and 
  910. timetotm functions.  The functions are similar to the mktime and localtime 
  911. functions in ANSI X3.159-1989, but the arguments don't use pointers and they 
  912. may be easier to remember.  If there is an error, the struct tm type will 
  913. contain the time "01/01/70 00:00:00" and the time_t type will contain the 
  914. value (time_t)-1, i.e. cast -1 to a time_t type.
  915.  
  916.      time_t time;
  917.      struct tm t;
  918.      
  919.      time = sftotime("12/25/94", "%m/%d/%y");
  920.      t = timetotm(time);
  921.  
  922.  
  923.  
  924. 9.0 REFERENCES
  925.  
  926. 1. ANSI X3.159-1989.  American National Standard for Information Systems -
  927.    Programming Language - C.  American National Standards Institute,
  928.    11 West 42nd Street, New York, NY 10036, 1990.
  929.  
  930.  
  931.  
  932. 10.0 INDEX
  933.  
  934. errno macro ............ 2.0, 2.1, 3.2
  935. rbegcolno macro ........ 2.1
  936. rclearerr function ..... 2.1
  937. rclose function ........ 6.1
  938. rcloseall function ..... 6.2
  939. rcolno macro ........... 2.1
  940. rcxtno macro ........... 3.5
  941. recin expression ....... 3.1, 6.1
  942. reof macro ............. 2.1, 5.5
  943. rerror function ........ 2.1, 5.6
  944. rerrmsg function ....... 2.1, 2.3
  945. rerrstr function ....... 2.1, 5.6
  946. rfix functions ......... 2.1
  947. rflds macro ............ 5.4
  948. rfldno macro ........... 2.1
  949. rbget functions ........ 5.1
  950. rbput functions ........ 5.1
  951. rcbget functions ....... 5.1
  952. rcbput functions ....... 5.1
  953. rcget functions ........ 5.1
  954. rcput functions ........ 5.1
  955. rget functions ......... 5.1
  956. rgetfldpos function .... 5.11
  957. rgetrec function ....... 4.1
  958. rgotofld function ...... 5.3
  959. rinit function ......... 2.3
  960. ristxtfld macro ........ 5.4
  961. risvalid function ...... 2.1
  962. rnames macro ........... 2.1
  963. rnbget functions ....... 5.1
  964. rnget functions ........ 5.1
  965. rnumfld function ....... 5.10
  966. ropen function  ........ 3.1
  967. rput functions ......... 5.1
  968. rrecs macro ............ 2.1, 4.3
  969. rrecno macro ........... 2.1, 4.4
  970. rresetrec macro ........ 4.6
  971. rsetbegcolno function .. 3.6
  972. rsetbegyr function ..... 3.7
  973. rsetcxtno function ..... 3.5
  974. rseterr function ....... 5.7
  975. rseterrfn function ..... 2.3
  976. rsetfldch function ..... 3.3
  977. rsetfldpos function .... 5.11
  978. rsetfldsiz function .... 3.4
  979. rsetfldstr function .... 2.1
  980. rsetrecsiz function .... 3.4
  981. rsetrecstr function .... 4.5
  982. rsettmfmt function ..... 3.3
  983. rsettxtch function ..... 3.3, 5.4
  984. rsetwarn function ...... 5.9
  985. rsetwarnfn function .... 2.3
  986. rskipfld macro  ........ 5.2
  987. rskipnfld function ..... 5.2
  988. rwarning function ...... 2.2, 5.8
  989. rwarnmsg function ...... 2.2, 2.3
  990. rwarnstr function ...... 2.2, 5.7
  991. scats macro ............ 7.2
  992. scpys macro ............ 7.2
  993. sctrimbegs function .... 7.1
  994. sctrimends function .... 7.1
  995. sctrims function ....... 7.1
  996. sftotime function ...... 8.1
  997. sftotm function ........ 8.1
  998. strimbegs macro ........ 7.1
  999. strimends macro ........ 7.1
  1000. strims macro ........... 7.1
  1001. timetotm function ...... 8.2
  1002. tmtotime function ...... 8.2
  1003.